﻿using Athena.Message;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Athena.Runtime.Client.Implementations
{
    using ExceptionHandler;
    using HealthChecks;
    using RouteAddress;
    using Transport;
    public class RpcInvokeService : IRpcInvokeService
    {
        private readonly ITransportClientFactory _transportClientFactory;

        private readonly IRouteResolver _routeResolver;
        private readonly ILogger _logger;

        public RpcInvokeService(ITransportClientFactory transportClientFactory, IRouteResolver routeResolver, IHealthCheckDispatch healthCheckDispatch, ILogger<RpcInvokeService> logger)
        {
            _transportClientFactory = transportClientFactory;
            _routeResolver = routeResolver;
            _logger = logger;
        }

        public Task<RpcInvokeResultMessage> InvokeAsync(RpcInvokeContext rpcInvokeContext)
        {
            return InvokeAsync(rpcInvokeContext, Task.Factory.CancellationToken);
        }

        public async Task<RpcInvokeResultMessage> InvokeAsync(RpcInvokeContext rpcInvokeContext, CancellationToken cancellationToken)
        {

            if (rpcInvokeContext == null)
            {
                throw new ArgumentNullException(nameof(rpcInvokeContext));
            }
            if (rpcInvokeContext.InvokeMessage == null)
            {
                throw new ArgumentNullException(nameof(rpcInvokeContext.InvokeMessage));
            }
            var baseRoute = await _routeResolver.Resolver(rpcInvokeContext.InvokeMessage.CorrelationId);

            if (baseRoute == null)
            {
                throw new RpcException(AthenaRpcInvokeResultCodeDisplay.RpcAddressException, $"无法解析服务Id：{rpcInvokeContext.InvokeMessage.CorrelationId}的地址信息。");
            }

            var endPoint = baseRoute.CreateEndPoint();

            var transportClient = _transportClientFactory.CreateClient(endPoint);
            return await transportClient.SendAsync(rpcInvokeContext.InvokeMessage);

        }
    }
}
